﻿using System;
using System.Collections.Generic;

namespace EmbeddedSharp.Core {

    /// <summary>
    /// The base class of functions
    /// </summary>
    public abstract class FuncNode : Node {

        /// <summary>
        /// The parameters
        /// </summary>
        public List<Node> Parameters {
            get;
            set;
        }

        /// <summary>
        /// The catalog of the function
        /// </summary>
        public string Catalog {
            get;
            set;
        }

        /// <summary>
        /// The description of the function
        /// </summary>
        public string Description {
            get;
            set;
        }

        public override string Type {
            get {
                return this.Value;
            }
        }

        /// <summary>
        /// Default constructor
        /// </summary>
        public FuncNode() {
            this.Parameters = new List<Node>();
            this.Precedence = Int32.MaxValue;
        }

        /// <summary>
        /// Constructor with name given
        /// </summary>
        /// <param name="value"></param>
        public FuncNode(string value)
            : this() {
            base.Value = value;
        }

        public FuncNode(string value, int precedence)
            : this(value) {
            this.Precedence = precedence;
        }

        /// <summary>
        /// The precedience of the function
        /// </summary>
        public int Precedence {
            get;
            set;
        }

        /// <summary>
        /// Return reversed function
        /// </summary>
        public virtual FuncNode GetReversedFunction(int index) {
            throw new NoReversedOperatorException(string.Format(
                "Function {0} cannot be transformed", this.Value));
        }

        /// <summary>
        /// Get default function
        /// </summary>
        public virtual FuncNode DefaultReversedFunction {
            get {
                return GetReversedFunction(0);
            }
        }

        /// <summary>
        /// Evaluate the expressions in the parameters
        /// </summary>
        public double[] EvaluateChildren() {
            double[] results = new double[Parameters.Count];
            for (int index = 0; index < Parameters.Count; index++) {
                results[index] = Convert.ToDouble(
                    Parameters[index].Evaluate());
            }

            return results;
        }

        /// <summary>
        /// Accepting visitor
        /// </summary>
        public override object Accept(IVisitor visitor) {
            return visitor.Visit(this);
        }
    }
}
